package vn.com.vega.chacha.v2.player;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import vn.com.vega.chacha.R;
import vn.com.vega.chacha.v2.ActivityBase;
import vn.com.vega.chacha.v2.Appinstant;
import vn.com.vega.chacha.v2.DialogConfirmPlaySong;
import vn.com.vega.chacha.v2.PlayerScreen;
import vn.com.vega.chacha.v2.widget.ChaChaWidgetProvider;
import vn.com.vega.music.clientserver.JsonSong;
import vn.com.vega.music.database.DataStore;
import vn.com.vega.music.objects.Song;
import vn.com.vega.music.utils.Const;
import vn.com.vega.music.utils.Util;
import vn.com.vega.music.utils.VegaLog;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.AudioManager.OnAudioFocusChangeListener;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Log;
import android.widget.RemoteViews;

import com.google.analytics.tracking.android.EasyTracker;

public class PlayerService extends Service {

	public static final int NOW = 1;

	public static final int NEXT = 2;

	public static final int LAST = 3;

	public static final int PLAYBACKSERVICE_STATUS = 1;

	public static final int SHUFFLE_OFF = 0;

	public static final int SHUFFLE_ON = 1;

	public static final int REPEAT_NONE = 0;

	public static final int REPEAT_CURRENT = 1;

	public static final int REPEAT_ALL = 2;

	public static final String PLAYSTATE_CHANGED = "vn.com.vega.chacha.playstatechanged";

	public static final String SONG_PREPARING = "vn.com.vega.chacha.preparingsong";

	public static final String SONG_END = "vn.com.vega.chacha.endsong";

	public static final String SONG_ERROR = "vn.com.vega.chacha.songerror";

	public static final String META_CHANGED = "vn.com.vega.chacha.metachanged";

	public static final String QUEUE_CHANGED = "vn.com.vega.chacha.queuechanged";

	public static final String SERVICECMD = "vn.com.vega.chacha.musicservicecommand";

	public static final String CMDNAME = "command";

	public static final String CMDTOGGLEPAUSE = "togglepause";

	public static final String CMDSTOP = "stop";

	public static final String CMDPAUSE = "pause";

	public static final String CMDPREVIOUS = "previous";

	public static final String CMDNEXT = "next";

	public static final String CMDPLAYNOW = "Play this song";

	public static final String CMDDONOTPLAY = "Do not play this song";

	public static final String TOGGLEPAUSE_ACTION = "vn.com.vega.chacha.musicservicecommand.togglepause";

	public static final String PLAY_PAUSE_ACTION = "vn.com.vega.chacha.musicservicecommand.pause";

	public static final String PREVIOUS_ACTION = "vn.com.vega.chacha.musicservicecommand.previous";

	public static final String NEXT_ACTION = "vn.com.vega.chacha.musicservicecommand.next";

	public static final String PAUSE_ACTION = "vn.com.vega.chacha.musicservicecommand.pause";

	private static final int TRACK_ENDED = 1;

	private static final int RELEASE_WAKELOCK = 2;

	private static final int SERVER_DIED = 3;

	private static final int FOCUSCHANGE = 4;

	private static final int FADEDOWN = 5;

	private static final int FADEUP = 6;

//	private static final int DOWN = 7;
//
//	private static final int UP = 8;
//
//	private static final int SETZEZOVOLUME = 9;
//
//	private static final int PREVIUS_AND_CONTINUES = 10;

	private WakeLock mWakeLock;

	private MultiPlayer mPlayer;
	private int mShuffleMode = SHUFFLE_OFF;
	private int mRepeatMode = REPEAT_NONE;
	private List<Song> mListSongPlay;
	private List<Song> mShufferList;
	private int indexCurrentSong = -1;
	private int indexLastSong = indexCurrentSong;
	private List<Song> listLastSongPlay;
	private List<Song> listLastShufferPlay;
	private AudioManager mAudioManager;
	private int mServiceStartId = -1;
	private boolean mServiceInUse = false;

	private boolean isDestroy = false;
	private Random mRandom;
	private List<Integer> mListSongPlayed;
	private DataStore mDataStore;

	private ChaChaWidgetProvider mAppWidgetProvider = ChaChaWidgetProvider
			.getInstance();

	// used to track what type of audio focus loss caused the playback to pause
	private boolean mPausedByTransientLossOfFocus = false;

	private final IBinder mBinder = new ServiceStub(this);

	protected static final String LOGTAG = PlayerService.class.getName();

	private OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener() {
		public void onAudioFocusChange(int focusChange) {
			mMediaplayerHandler.obtainMessage(FOCUSCHANGE, focusChange, 0)
					.sendToTarget();
		}
	};

	private Handler mMediaplayerHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case SERVER_DIED:
				// TODO: do something here
				break;
			case TRACK_ENDED:
				next();
				break;
			case RELEASE_WAKELOCK:
				mWakeLock.release();
				break;
			case FADEDOWN:
				mPlayer.setVolume(0.2f);
				break;
			case FADEUP:
				mPlayer.setVolume(1.0f);
				break;

			case FOCUSCHANGE:
				// This code is here so we can better synchronize it with
				// the code that
				// handles fade-in
				switch (msg.arg1) {
				case AudioManager.AUDIOFOCUS_LOSS:
					Log.e(LOGTAG, "AudioFocus: received AUDIOFOCUS_LOSS");
					if (isPlaying()) {
						mPausedByTransientLossOfFocus = false;
					}
					pause();
					break;
				case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
					Log.e(LOGTAG,
							"AudioFocus: received AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK");
					mMediaplayerHandler.removeMessages(FADEUP);
					mMediaplayerHandler.sendEmptyMessage(FADEDOWN);
					break;
				case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
					Log.e(LOGTAG,
							"AudioFocus: received AUDIOFOCUS_LOSS_TRANSIENT");
					if (isPlaying()) {
						mPausedByTransientLossOfFocus = true;
					}
					pause();
					break;
				case AudioManager.AUDIOFOCUS_GAIN:
					Log.e(LOGTAG, "AudioFocus: received AUDIOFOCUS_GAIN");
					if (!isPlaying() && mPausedByTransientLossOfFocus) {
						mPausedByTransientLossOfFocus = false;
						play(); // also queues a fade-in
					} else {
						mMediaplayerHandler.removeMessages(FADEDOWN);
						mMediaplayerHandler.sendEmptyMessage(FADEUP);
					}
					break;
				default:
					Log.e(LOGTAG, "Unknown audio focus change code");
				}
				break;

			default:
				break;
			}
		}
	};

	private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			String cmd = intent.getStringExtra(CMDNAME);
			VegaLog.e(PlayerService.class.getName(),
					"mIntentReceiver.onReceive " + action + " / " + cmd);
			if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {
				next();
			} else if (CMDPREVIOUS.equals(cmd)
					|| PREVIOUS_ACTION.equals(action)) {
				prev();
			} else if (CMDTOGGLEPAUSE.equals(cmd)
					|| TOGGLEPAUSE_ACTION.equals(action)) {
				if (isPlaying()) {
					pause();
					mPausedByTransientLossOfFocus = false;
				} else {
					play();
				}
			} else if (CMDPAUSE.equals(cmd) || PAUSE_ACTION.equals(action)) {
				pause();
				mPausedByTransientLossOfFocus = false;
			} else if (CMDSTOP.equals(cmd)) {
				pause();
				mPausedByTransientLossOfFocus = false;
				seek(0);
			} else if (ChaChaWidgetProvider.CMDAPPWIDGETUPDATE.equals(cmd)) {
				// Someone asked us to refresh a set of specific widgets,
				// probably
				// because they were just added.
				int[] appWidgetIds = intent
						.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
				mAppWidgetProvider.performUpdate(PlayerService.this,
						appWidgetIds);
			} else if (ChaChaWidgetProvider.CMDAPPWIDGETUPDATETHUMB.equals(cmd)) {
				String urlThumb = intent
						.getStringExtra(ChaChaWidgetProvider.IMAGE_URL);
				int[] appWidgetIds = intent
						.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
				if (!Util.checkStringIsemptyOrNull(urlThumb)) {
					if (downLoadImageThumb != null) {
						downLoadImageThumb.cancel(true);
					}
					downLoadImageThumb = new DownLoadImageThumb(
							PlayerService.this, appWidgetIds);
					downLoadImageThumb.execute(urlThumb);
				}

			} else if (CMDPLAYNOW.equals(cmd)) {
				if (playSong != null) {
					playSong.start();
				}
			} else if (CMDDONOTPLAY.equals(cmd)) {
				playSong = null;
				indexCurrentSong = indexLastSong;
				mListSongPlay = listLastSongPlay;
				mShufferList = listLastShufferPlay;
			}
		}
	};

	private DownLoadImageThumb downLoadImageThumb;

	static class DownLoadImageThumb extends AsyncTask<String, Void, Bitmap> {
		WeakReference<PlayerService> playerServiceRfc;
		int[] appWidgetIds;

		public DownLoadImageThumb(PlayerService service, int[] widgetIds) {
			playerServiceRfc = new WeakReference<PlayerService>(service);
			appWidgetIds = widgetIds;
		}

		private boolean checkIsLive() {
			PlayerService playerService = playerServiceRfc.get();
			if (playerService == null || playerService.isDestroy) {
				return false;
			}
			return false;
		}

		@Override
		protected Bitmap doInBackground(String... params) {
			// TODO Auto-generated method stub
			return Util.loadBitmap(params[0]);
		}

		@Override
		protected void onPostExecute(Bitmap result) {
			// TODO Auto-generated method stub
			if (isCancelled() || result == null || checkIsLive()) {
				return;
			}

			PlayerService playerService = playerServiceRfc.get();
			playerService.mAppWidgetProvider.updateThumb(playerService,
					appWidgetIds, result);
		}

	}

	private void next() {
		// TODO: next song
		synchronized (this) {
			if (mRepeatMode == REPEAT_CURRENT) {
				mPlayer.seek(0);
				mPlayer.start();
				return;
			}
			indexLastSong = indexCurrentSong;
			if (mShuffleMode == SHUFFLE_OFF) {
				if (indexCurrentSong < mListSongPlay.size() - 1) {
					indexCurrentSong += 1;
					play(mListSongPlay.get(indexCurrentSong));
				} else {
					if (mRepeatMode == REPEAT_ALL) {
						indexCurrentSong = 0;
						play(mListSongPlay.get(indexCurrentSong));
					}
				}

			} else {
				if (mListSongPlayed.size() < mListSongPlay.size()) {
					do {
						indexCurrentSong = mRandom
								.nextInt(mListSongPlay.size());
					} while (mListSongPlayed.contains(Integer
							.valueOf(indexCurrentSong)));
					play(mShufferList.get(indexCurrentSong));
				} else {
					if (mRepeatMode == REPEAT_ALL) {
						mListSongPlayed.clear();
						indexCurrentSong = 0;
						play(mShufferList.get(indexCurrentSong));
					}
				}
			}
			mListSongPlayed.add(Integer.valueOf(indexCurrentSong));
		}
	}

	private void prev() {
		synchronized (this) {
			if (mRepeatMode == REPEAT_CURRENT) {
				mPlayer.seek(0);
				mPlayer.start();
				return;
			}
			indexLastSong = indexCurrentSong;
			if (mShuffleMode == SHUFFLE_OFF) {
				if (indexCurrentSong > 0) {
					indexCurrentSong -= 1;
					play(mListSongPlay.get(indexCurrentSong));
				} else {
					if (mRepeatMode == REPEAT_ALL) {
						indexCurrentSong = mListSongPlay.size() - 1;
						play(mListSongPlay.get(indexCurrentSong));
					}
				}

			} else {
				if (indexCurrentSong > 0) {
					indexCurrentSong -= 1;
					play(mShufferList.get(indexCurrentSong));
				} else {
					if (mRepeatMode == REPEAT_ALL) {
						indexCurrentSong = mListSongPlay.size() - 1;
						play(mShufferList.get(indexCurrentSong));
					}
				}
			}
			mListSongPlayed.add(Integer.valueOf(indexCurrentSong));
		}
	}

	public boolean isPlaying() {
		synchronized (this) {
			if (mPlayer == null) {
				return false;
			}
			return mPlayer.isPlaying();
		}
	}

	private void gotoIdleState() {
		mDelayedStopHandler.removeCallbacksAndMessages(null);
		Message msg = mDelayedStopHandler.obtainMessage();
		mDelayedStopHandler.sendMessageDelayed(msg, IDLE_DELAY);
		stopForeground(true);
	}

	private void pause() {
		synchronized (this) {
			if (mPlayer != null && mPlayer.isInitialized()) {
				mPlayer.pause();
				gotoIdleState();
				notifyChange(PLAYSTATE_CHANGED);

			}
		}
	}

	@TargetApi(8)
	private void play() {
		synchronized (this) {
			if (Build.VERSION.SDK_INT >= 8) {
				mAudioManager
						.requestAudioFocus(mAudioFocusListener,
								AudioManager.STREAM_MUSIC,
								AudioManager.AUDIOFOCUS_GAIN);
			}

			if (mPlayer != null && mPlayer.isInitialized()) {
				// if we are at the end of the song, go to the next song first
				long duration = mPlayer.duration();
				if (mRepeatMode != REPEAT_CURRENT && duration > 0
						&& mPlayer.position() >= duration) {
					next();
				}
				mPlayer.start();

				RemoteViews views = new RemoteViews(getPackageName(),
						R.layout.statusbar);
				views.setImageViewResource(R.id.icon,
						R.drawable.ic_notify_playing);
				views.setTextViewText(R.id.trackname, getCurrentSong().title);
				views.setTextViewText(R.id.artistalbum,
						getCurrentSong().artist_name);

				Notification status = new Notification();
				status.contentView = views;
				status.flags |= Notification.FLAG_ONGOING_EVENT;
				status.icon = R.drawable.ic_notyfi_now_playing;
				status.contentIntent = PendingIntent.getActivity(this, 0,
						new Intent(this, PlayerScreen.class)
								.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
										| Intent.FLAG_ACTIVITY_CLEAR_TOP), 0);
				startForeground(PLAYBACKSERVICE_STATUS, status);
				notifyChange(PLAYSTATE_CHANGED);

			}
		}
	}

	private void cancelNotify(String what) {
		Intent intent = new Intent(what);
		removeStickyBroadcast(intent);
	}

	private void notifyChange(String what) {

		Intent i = new Intent(what);
		// LocalBroadcastManager.getInstance(this).sendBroadcastSync(i);
		// sendBroadcast(i);//
		if (PLAYSTATE_CHANGED.equalsIgnoreCase(what)) {
			removeStickyBroadcast(new Intent(SONG_PREPARING));
		}
		sendStickyBroadcast(i);
		if (what.equals(QUEUE_CHANGED)) {
			// saveQueue(true);
		} else {
			// saveQueue(false);
		}

		mAppWidgetProvider.notifyChange(this, what);
	}

	private void seek(long position) {
		synchronized (this) {
			if (mPlayer != null && mPlayer.isInitialized()) {
				mPlayer.seek(position);
			}
		}
	}

	private void openList(List<Song> listSong, int position) {
		synchronized (this) {
			if (listSong == null || listSong.size() == 0 || position < 0
					|| position > listSong.size()) {
				// Some thing wrong here
				return;
			}
			indexLastSong = indexCurrentSong;
			listLastSongPlay = mListSongPlay;
			listLastShufferPlay = mShufferList;
			
			mListSongPlayed = new ArrayList<Integer>();
			this.mListSongPlay = listSong;
			Song song = mListSongPlay.get(position);
			indexCurrentSong = position;
			play(song);
		}
	}

	private void openSongAt(int position) {
		try {
			Song song = mListSongPlay.get(position);
			if (song != null) {
				play(song);
				indexLastSong = indexCurrentSong;
				indexCurrentSong = position;
				mListSongPlayed.add(Integer.valueOf(indexCurrentSong));
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private Thread playSong = null;

	private void play(final Song song) {
		synchronized (this) {
			EasyTracker.getTracker().trackEvent(
					ActivityBase.Category.selectItem,
					ActivityBase.Action.playsong, song.title, (long) 1);
			playSong = new Thread() {
				@Override
				public void run() {
					try {
						if (mPlayer != null) {
							mPlayer.release();
						}
					} catch (Exception e) {
						// TODO: handle exception
						e.printStackTrace();
					}
					Uri songUri = JsonSong.loadSongUri(song);
					if (songUri == null) {
						return;
					}
					mPlayer = new MultiPlayer();
					notifyChange(SONG_PREPARING);
					mPlayer.setDataSource(songUri.toString());
					if (mPlayer.isInitialized()) {
						play();
					}
					playSong = null;
				}
			}/* .start() */;
//			if (Util.checkStringIsemptyOrNull(song.listenPrice)) {
//				playSong.start();
//			} else {
				Intent intent = new Intent(this, DialogConfirmPlaySong.class);
				intent.putExtra(DialogConfirmPlaySong.KEY_CONFIRM_TYPE, DialogConfirmPlaySong.CONFIRM_PLAY_SONG);
				intent.putExtra(DialogConfirmPlaySong.KEY_CONFIRM_MESSAGE, 
						"Bạn sẽ bì trừ " + song.listenPrice + " khi nghe bài hát này.\n"
						+ Appinstant.warningMessage);
				intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
				startActivity(intent);
//			}
		}
	}

	// private void genShufferList(List<Song> list, int position) {
	//
	// for (int i = 0; i < position; i++) {
	// // remove all song had played
	// list.remove(i);
	// }
	// Song song = list.get(0);
	// list.remove(0);
	// Collections.shuffle(list);
	// list.add(0, song);
	// }

	private long getDuration() {
		synchronized (this) {
			try {
				if (mPlayer.isInitialized()) {
					return mPlayer.duration();
				}
			} catch (Exception e) {
				// TODO: handle exception
			}
			return 0;
		}
	}

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
		mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
		mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this
				.getClass().getName());
		mWakeLock.setReferenceCounted(false);
		mPlayer = new MultiPlayer();
		mPlayer.setHandler(mMediaplayerHandler);

		IntentFilter commandFilter = new IntentFilter();
		commandFilter.addAction(SERVICECMD);
		commandFilter.addAction(TOGGLEPAUSE_ACTION);
		commandFilter.addAction(PAUSE_ACTION);
		commandFilter.addAction(NEXT_ACTION);
		commandFilter.addAction(PREVIOUS_ACTION);
		commandFilter.addAction(CMDDONOTPLAY);
		commandFilter.addAction(CMDPLAYNOW);
		registerReceiver(mIntentReceiver, commandFilter);

		cancelNotify(PLAYSTATE_CHANGED);
		cancelNotify(SONG_PREPARING);

		Settings.System.putInt(getContentResolver(),
				Settings.System.WIFI_SLEEP_POLICY,
				Settings.System.WIFI_SLEEP_POLICY_NEVER);

		mDataStore = DataStore.getInstance();
		EasyTracker.getInstance().setContext(this);
		try {
			mRepeatMode = Integer.valueOf(
					mDataStore.getConfig(Const.PLAYER_REPEATE_MODE)).intValue();
		} catch (Exception e) {
			// TODO: handle exception
			mRepeatMode = REPEAT_NONE;
		}
		try {
			mShuffleMode = Integer.valueOf(
					mDataStore.getConfig(Const.PLAYER_SHUFFLE_MODE)).intValue();
		} catch (Exception e) {
			// TODO: handle exception
			mShuffleMode = SHUFFLE_OFF;
		}

	}

	/**
	 * Provides a unified interface for dealing with midi files and other media
	 * files.
	 */
	private class MultiPlayer {
		private MediaPlayer mMediaPlayer = new MediaPlayer();

		private Handler mHandler;

		private boolean mIsInitialized = false;

		public MultiPlayer() {
			mMediaPlayer.setWakeMode(PlayerService.this,
					PowerManager.PARTIAL_WAKE_LOCK);
		}

		public void setDataSource(String path) {
			try {
				mMediaPlayer.reset();
				mMediaPlayer.setOnPreparedListener(null);
				if (path.startsWith("content://")) {
					mMediaPlayer.setDataSource(PlayerService.this,
							Uri.parse(path));
				} else {
					mMediaPlayer.setDataSource(path);
				}
				mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
				mMediaPlayer.prepare();
			} catch (IOException ex) {
				// TODO: notify the user why the file couldn't be opened
				mIsInitialized = false;
				return;
			} catch (IllegalArgumentException ex) {
				// TODO: notify the user why the file couldn't be opened
				mIsInitialized = false;
				return;
			}
			mMediaPlayer.setOnCompletionListener(completeListener);
			mMediaPlayer.setOnErrorListener(errorListener);
			mIsInitialized = true;
		}

		public boolean isInitialized() {
			return mIsInitialized;

		}

		public boolean isPlaying() {
			if (isInitialized()) {
				return mMediaPlayer.isPlaying();
			}
			return false;
		}

		public void start() {
			VegaLog.e(PlayerService.class.getName(), "MultiPlayer.start called");
			mMediaPlayer.start();
		}

		public void stop() {
			mMediaPlayer.reset();
			mIsInitialized = false;
			stopForeground(true);
		}

		/**
		 * You CANNOT use this player anymore after calling release()
		 */
		public void release() {
			stop();
			mMediaPlayer.release();
			mAudioManager.abandonAudioFocus(mAudioFocusListener);
		}

		public void pause() {
			mMediaPlayer.pause();
		}

		public void setHandler(Handler handler) {
			mHandler = handler;
		}

		MediaPlayer.OnCompletionListener completeListener = new MediaPlayer.OnCompletionListener() {
			public void onCompletion(MediaPlayer mp) {
				// Acquire a temporary wakelock, since when we return from
				// this callback the MediaPlayer will release its wakelock
				// and allow the device to go to sleep.
				// This temporary wakelock is released when the RELEASE_WAKELOCK
				// message is processed, but just in case, put a timeout on it.
				mWakeLock.acquire(30000);
				// if (mHandler != null) {
				mMediaplayerHandler.sendEmptyMessage(TRACK_ENDED);
				mMediaplayerHandler.sendEmptyMessage(RELEASE_WAKELOCK);
				mAudioManager.abandonAudioFocus(mAudioFocusListener);
				gotoIdleState();
				// }
			}
		};

		MediaPlayer.OnErrorListener errorListener = new MediaPlayer.OnErrorListener() {
			public boolean onError(MediaPlayer mp, int what, int extra) {
				switch (what) {

				case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
					mIsInitialized = false;
					mMediaPlayer.release();
					// Creating a new MediaPlayer and settings its wakemode
					// does not
					// require the media service, so it's OK to do this now,
					// while the
					// service is still being restarted
					mMediaPlayer = new MediaPlayer();
					mMediaPlayer.setWakeMode(PlayerService.this,
							PowerManager.PARTIAL_WAKE_LOCK);
					mHandler.sendMessageDelayed(
							mHandler.obtainMessage(SERVER_DIED), 2000);
					return true;
				default:
					Log.d("MultiPlayer", "Error: " + what + "," + extra);
					break;
				}
				return false;
			}
		};

		public long duration() {
			return mMediaPlayer.getDuration();
		}

		public long position() {
			return mMediaPlayer.getCurrentPosition();
		}

		public long seek(long whereto) {
			mMediaPlayer.seekTo((int) whereto);
			return whereto;
		}

		public void setVolume(float vol) {
			mMediaPlayer.setVolume(vol, vol);
		}
	}

	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		VegaLog.e(PlayerService.class.getName(), "on bind");
		mDelayedStopHandler.removeCallbacksAndMessages(null);
		mServiceInUse = true;
		return mBinder;
	}

	@Override
	public void onRebind(Intent intent) {
		mDelayedStopHandler.removeCallbacksAndMessages(null);
		mServiceInUse = true;
	}

	@Override
	public boolean onUnbind(Intent intent) {
		mServiceInUse = false;
		if (isPlaying() || mPausedByTransientLossOfFocus) {
			// something is currently playing, or will be playing once
			// an in-progress action requesting audio focus ends, so don't stop
			// the service now.
			return true;
		}
		// If there is a playlist but playback is paused, then wait a while
		// before stopping the service, so that pause/resume isn't slow.

		// Also delay stopping the service if we're transitioning between
		// tracks.
		if (mMediaplayerHandler.hasMessages(TRACK_ENDED)) {
			Message msg = mDelayedStopHandler.obtainMessage();
			mDelayedStopHandler.sendMessageDelayed(msg, IDLE_DELAY);
			return true;
		}

		// No active playlist, OK to stop the service right now
		stopSelf(mServiceStartId);
		return true;
	}

	static class ServiceStub extends IMediaPlaybackService.Stub {
		WeakReference<PlayerService> mService;

		public ServiceStub(PlayerService service) {
			mService = new WeakReference<PlayerService>(service);
		}

		@Override
		public void openList(List<Song> listSong, int position)
				throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				mService.get().openList(listSong, position);
			}

		}

		@Override
		public void openSongAt(int position) {
			if (mService.get() != null) {
				mService.get().openSongAt(position);
			}
		}

		@Override
		public long getDuration() throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				return mService.get().getDuration();
			} else {
				return 0;
			}

		}

		@Override
		public long getPosition() throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				return mService.get().getPosition();
			} else {
				return 0;
			}
		}

		@Override
		public Song getCurrentSong() throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				return mService.get().getCurrentSong();
			} else {
				return null;
			}
		}

		@Override
		public List<Song> getCurrentListPlay() throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				return mService.get().getCurrentListPlay();
			} else {
				return null;
			}
		}

		@Override
		public void setShufferMode(int shufferMode) throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				mService.get().setShufferMode(shufferMode);
			}
		}

		@Override
		public void setRepeateMode(int repeateMode) throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				mService.get().setRepeateMode(repeateMode);
			}
		}

		@Override
		public int getShufferMode() throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				return mService.get().getShufferMode();
			} else {
				return SHUFFLE_OFF;
			}
		}

		@Override
		public int getRepeateMode() throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				return mService.get().getRepeateMode();
			} else {
				return REPEAT_NONE;
			}
		}

		@Override
		public boolean isPlaying() throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				return mService.get().isPlaying();
			} else {
				return false;
			}
		}

		@Override
		public void stop() throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				mService.get().stop();
			}
		}

		@Override
		public void pause() throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				mService.get().pause();
			}
		}

		@Override
		public void play() throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				mService.get().play();
			}
		}

		@Override
		public void prev() throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				mService.get().prev();
			}
		}

		@Override
		public void next() throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				mService.get().next();
			}
		}

		@Override
		public void seek(long pos) throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				mService.get().seek(pos);
			}
		}

		@Override
		public void addToPlaylist(Song songAdd, int position)
				throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				mService.get().addToPlaylist(songAdd, position);
			}
		}

		@Override
		public void removeFromPlayList(int position) throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				mService.get().removeFromPlayList(position);
			}
		}

		@Override
		public void setListSong(List<Song> listSong) throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				mService.get().setListSong(listSong);
			}
		}

		@Override
		public int getIndexCurrentSong() {
			if (mService.get() != null) {
				return mService.get().getIndexCurrentSong();
			}
			return -1;
		}

		@Override
		public boolean insertToNowPlaying(Song song) throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				return mService.get().insertToNowPlaying(song);
			}
			return false;
		}

		@Override
		public boolean playerIsInit() throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				return mService.get().playerIsInit();
			}
			return false;
		}

		@Override
		public boolean insertListSongToNowPlaying(List<Song> listSong)
				throws RemoteException {
			// TODO Auto-generated method stub
			if (mService.get() != null) {
				return mService.get().insertListSongToNowPlaying(listSong);
			}
			return false;
		}

	}

	public boolean playerIsInit() {
		// TODO Auto-generated method stub
		synchronized (this) {
			if (mPlayer != null && mPlayer.isInitialized()) {
				return true;
			}
			return false;
		}
	}

	public void setListSong(List<Song> listSong) {
		// TODO Auto-generated method stub

	}

	public boolean insertToNowPlaying(Song song) {
		// TODO Auto-generated method stub
		synchronized (this) {
			try {
				if (mListSongPlay == null) {
					List<Song> listSong = new ArrayList<Song>();
					listSong.add(song);
					if (mShuffleMode == SHUFFLE_ON) {

					}
					openList(listSong, 0);
				} else {
					mListSongPlay.add(indexCurrentSong + 1, song);
				}
				return true;
			} catch (Exception e) {
				// TODO: handle exception
				return false;
			}
		}
	}

	public boolean insertListSongToNowPlaying(List<Song> listSong) {

		synchronized (this) {
			try {
				if (mListSongPlay == null) {
					openList(listSong, 0);
				} else {
					mListSongPlay.addAll(indexCurrentSong + 1, listSong);
				}
				return true;
			} catch (Exception e) {
				// TODO: handle exception
				return false;
			}
		}
	}

	private int getIndexCurrentSong() {
		synchronized (this) {
			return indexCurrentSong;
		}
	}

	public long getPosition() {
		// TODO Auto-generated method stub
		synchronized (this) {
			try {
				if (mPlayer.isInitialized()) {
					return mPlayer.position();
				} else {
					return 0;
				}
			} catch (Exception e) {
				// TODO: handle exception
				return 0;
			}
		}
	}

	public Song getCurrentSong() {
		// TODO Auto-generated method stub
		synchronized (this) {
			if (mListSongPlay != null && indexCurrentSong != -1
					&& indexCurrentSong < mListSongPlay.size()
					&& indexCurrentSong >= 0) {
				return mListSongPlay.get(indexCurrentSong);
			}
			return null;
		}
	}

	public List<Song> getCurrentListPlay() {
		// TODO Auto-generated method stub
		return mListSongPlay;
	}

	public void setShufferMode(int shufferMode) {
		// TODO Auto-generated method stub
		if (shufferMode == mShuffleMode) {
			// Do nothing
			return;
		}
		mShuffleMode = shufferMode;
		if (shufferMode == SHUFFLE_ON) {
			mRandom = new Random(System.currentTimeMillis());
		}

		// if (shufferMode == SHUFFLE_OFF) {
		// // Song song = mShufferList.get(indexCurrentSong);
		// // indexCurrentSong = mListSongPlay.indexOf(song);
		// // mShufferList.clear();
		// } else {
		// mRandom = new Random(System.currentTimeMillis());
		// // mShufferList = new ArrayList<Song>();
		// // mShufferList.addAll(mListSongPlay);
		// // genShufferList(mShufferList, indexCurrentSong);
		// // indexCurrentSong = 0;
		// }
		// mShuffleMode = shufferMode;
	}

	public void setRepeateMode(int repeateMode) {
		// TODO Auto-generated method stub
		mRepeatMode = repeateMode;
	}

	public int getShufferMode() {
		// TODO Auto-generated method stub
		return mShuffleMode;
	}

	public int getRepeateMode() {
		// TODO Auto-generated method stub
		return mRepeatMode;
	}

	public void stop() {
		// TODO Auto-generated method stub
		synchronized (this) {
			if (mPlayer != null && mPlayer.isInitialized()) {
				mPlayer.stop();
				notifyChange(PLAYSTATE_CHANGED);
			}
		}
	}

	public void addToPlaylist(Song songAdd, int position) {
		// TODO Auto-generated method stub

	}

	public void removeFromPlayList(int position) {
		// TODO Auto-generated method stub

	}

	// interval after which we stop the service when idle
	private static final int IDLE_DELAY = 60000;

	private Handler mDelayedStopHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			// Check again to make sure nothing is playing right now
			if (isPlaying() || mPausedByTransientLossOfFocus || mServiceInUse
					|| mMediaplayerHandler.hasMessages(TRACK_ENDED)) {
				return;
			}
			// save the queue again, because it might have changed
			// since the user exited the music app (because of
			// party-shuffle or because the play-position changed)
			// saveQueue(true);
			stopSelf(mServiceStartId);
		}
	};

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		VegaLog.e(PlayerService.class.getName(), "on onstart command");
		mServiceStartId = startId;

		if (intent != null) {
			String action = intent.getAction();
			String cmd = intent.getStringExtra("command");
			VegaLog.e("onStartCommand " + action + " / " + cmd);

			if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {
				next();
			} else if (CMDPREVIOUS.equals(cmd)
					|| PREVIOUS_ACTION.equals(action)) {
				prev();
			} else if (CMDTOGGLEPAUSE.equals(cmd)
					|| TOGGLEPAUSE_ACTION.equals(action)) {
				if (isPlaying()) {
					pause();
					mPausedByTransientLossOfFocus = false;
				} else {
					play();
				}
			} else if (CMDPAUSE.equals(cmd) || PAUSE_ACTION.equals(action)) {
				pause();
				mPausedByTransientLossOfFocus = false;
			} else if (CMDSTOP.equals(cmd)) {
				pause();
				mPausedByTransientLossOfFocus = false;
				seek(0);
			}
		}

		// make sure the service will shut down on its own if it was
		// just started but not bound to and nothing is playing
		mDelayedStopHandler.removeCallbacksAndMessages(null);
		Message msg = mDelayedStopHandler.obtainMessage();
		mDelayedStopHandler.sendMessageDelayed(msg, IDLE_DELAY);
		return START_STICKY;
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		Settings.System.putInt(getContentResolver(),
				Settings.System.WIFI_SLEEP_POLICY,
				Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
		DataStore dataStore = DataStore.getInstance();
		dataStore.setConfig(Const.PLAYER_SHUFFLE_MODE, mShuffleMode + "");
		dataStore.setConfig(Const.PLAYER_REPEATE_MODE, mRepeatMode + "");

		EasyTracker.getInstance().setContext(null);

		isDestroy = true;
		stopForeground(true);
		unregisterReceiver(mIntentReceiver);
		mMediaplayerHandler.removeCallbacksAndMessages(null);
		mDelayedStopHandler.removeCallbacksAndMessages(null);
		if (mPlayer != null) {
			try {
				mPlayer.release();
				mPlayer = null;
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
		mWakeLock.release();
	}

}
